﻿using System.Collections.Generic;
using System.Web.Mvc;
using System.Windows.Media;
using System.Xml.Linq;
using CharacterModel;
using Framework.Model;
using MvcApplication1.Views.Utility;
using CharacterModel.Extensions;
using System.Linq;
using Ninject;

namespace MvcApplication1.Controllers
{
    public class FaceDisplayController : Controller
    {
        [Inject]
        public Repository Repository { get; set; }

        private readonly FaceModelFactory _faceModelFactory;

        public FaceDisplayController(FaceModelFactory faceModelFactory)
        {
            _faceModelFactory = faceModelFactory;
        }

        public ActionResult GetFeature(int featureId)
        {
            var feature = Repository.Get<Feature>(featureId);
            var layerData = feature
                .DynamicLayers
                .Select(layer => new
                                     {
                                         layer.LayerType.Id,
                                         Pathes = layer.Paths.Select(svg => svg.SvgPath)
                                     });
            var jsonData = new
                               {
                                   feature.Id,
                                   FeatureTypeId = feature.FeatureType.Id,
                                   ViewBox = new
                                                 {
                                                     X = feature.BoundsLeft,
                                                     Y = feature.BoundsTop,
                                                     feature.Bounds.Width,
                                                     feature.Bounds.Height
                                                 },
                                   Layers = layerData,
                                   Markers = feature.MarkerPoints.Select(mp => new
                                                                                   {
                                                                                       mp.MarkerPointType.Id,
                                                                                       X = mp.PointX,
                                                                                       Y = mp.PointY
                                                                                   })
                               };

            return Json(jsonData, JsonRequestBehavior.AllowGet);
        }

        public ActionResult GetSvg(string faceIdentifier, bool showMarkers)
        {
            var transformDictionary = new Dictionary<string, XElement>();

            var faceModel = _faceModelFactory.Get(faceIdentifier);
            var element = new XElement("svg",
                                       new XAttribute("viewBox", string.Format("{0} {1} {2} {3}",
                                                                               faceModel.FeatureBounds.Left,
                                                                               faceModel.FeatureBounds.Top,
                                                                               faceModel.FeatureBounds.Width,
                                                                               faceModel.FeatureBounds.Height)));
            var gElement = new XElement("g");
            element.Add(gElement);
            foreach (var colorRegion in faceModel.GetColorRegions())
            {
                var gTransform = "";
                if (colorRegion.Geometry != null && colorRegion.Geometry.Transform != Transform.Identity)
                {
                    var transformGroup = (TransformGroup)colorRegion.Geometry.Transform;
                    foreach (var transform in transformGroup.Children.Reverse())
                    {
                        var translate = transform as TranslateTransform;
                        if (translate != null)
                        {
                            gTransform += (gTransform.Length > 0 ? " " : "") + string.Format("translate({0},{1})", translate.X, translate.Y);
                            continue;
                        }
                        var scale = transform as ScaleTransform;
                        if (scale != null)
                        {
                            gTransform += (gTransform.Length > 0 ? " " : "") + string.Format("scale({0},{1})", scale.ScaleX, scale.ScaleY);
                            continue;
                        }
                    }
                }

                if (!transformDictionary.ContainsKey(gTransform))
                {
                    transformDictionary[gTransform] = new XElement("g",
                                                                   string.IsNullOrEmpty(gTransform)
                                                                       ? null
                                                                       : new XAttribute("transform", gTransform));
                }
                transformDictionary[gTransform].Add(new XElement("path",
                                                                 new XAttribute("layer_type", colorRegion.SourceLayer),
                                                                 new XAttribute("style", colorRegion.Color.GetSvgStyle()),
                                                                 new XAttribute("d", colorRegion.Path)));
            }
            foreach (var value in transformDictionary.Values)
                gElement.Add(value);

            if (showMarkers)
            {
                var markerCircles = faceModel
                    .Features
                    .SelectMany(f => f.MarkerPoints)
                    .Select(m => new XElement("circle",
                                              new XAttribute("cx", m.PointX),
                                              new XAttribute("cy", m.PointY),
                                              new XAttribute("r", "10"),
                                              new XAttribute("stroke", "black"),
                                              new XAttribute("stroke-width", "2"),
                                              new XAttribute("fill", "red"),
                                              new XAttribute("markerName", m.MarkerPointType.MarkerPointTypeEnum),
                                              new XAttribute("onmouseover",
                                                             "updateMarkerName('" +
                                                             m.MarkerPointType.MarkerPointTypeEnum + "')")))
                    .ToList();
                foreach (var marker in markerCircles)
                    gElement.Add(marker);
            }

            return new ContentResult {Content = element.ToString(), ContentType = "text/xml"};
        }

        public ActionResult Display(string faceIdentifier, int width, int height)
        {
            var faceModel = _faceModelFactory.Get(faceIdentifier);

            return new PngResult(dc =>
                                     {
                                         foreach (var colorRegion in faceModel.GetColorRegions())
                                             dc.DrawGeometry(new SolidColorBrush(colorRegion.Color), null, colorRegion.Geometry);
                                     }, width, height);
        }
    }
}
